<?php
/**
 * Zhub - A PHP Framework For API Developer
 *
 * This file is part of the Zhub package.
 *
 * (c) YiLong Fan <fantiq@163.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author fanyilong <fantiq@163.com>
 * @copyright 2017 fanyilong. All rights reserved.
 * @package Zhub
 * @date 18-3-8
 */

namespace Zhub\DependencyInject;

use Closure;
use ReflectionClass;

class Container
{
    private static $container = null;

    private static $objectCollection = [];

    public static function getInstance()
    {
        if (!self::$container) {
            self::$container = new self();
        }
        return self::$container;
    }

    public function binding(string $concrete, object $entity)
    {
        if (is_callable($entity)) {
            $entity = call_user_func($entity);
        }
        if (!$entity instanceof $concrete) {
            //
        }
        self::$objectCollection[$concrete] = $entity;
    }

    public function get(){}

    public function make(){}

    public function inject(string $className)
    {
        if (!class_exists($className)) {

        }
        $reflection = new ReflectionClass($className);
        $this->build($reflection);
    }

    protected function build(ReflectionClass $reflection)
    {
        // instantiable
        if (! $reflection->isInstantiable()) {
            //
        }
        // constructor
        $constructor = $reflection->getConstructor();
        if (!$constructor) {
            $instance = $reflection->newInstanceWithoutConstructor();
            self::$objectCollection[$reflection->getName()] = $instance;
            return $instance;
        }
        // dependency
        $dependencies = $constructor->getParameters();
        $parameters = $this->resolveDependencies($dependencies);
        return $reflection->newInstanceArgs($parameters);
    }

    protected function resolveDependencies(array $dependencies)
    {
        $parameters = [];
        foreach ($dependencies as $dependency) {
            $class = $dependency->getClass();
            if ($class) {
                $parameters[] = $this->build($class);
            }
            elseif ($dependency->isDefaultValueAvailable()) {
                $parameters[] = $dependency->getDefaultValue();
            }
            else {
                throw new \Exception();
            }
        }
        return $parameters;
    }

}
